"""链表"""
from .exceptions import IndexErrorOfStructure, ElementNotExist


class LinkedList:
    class Node:
        """链表的节点类"""
        def __init__(self, data):
            self.data = data
            self.next_node = None

    def __init__(self):
        self.dummy_head = LinkedList.Node(None)
        self._size = 0

    def get_size(self):
        return self._size

    def is_empty(self):
        return self._size == 0

    def add(self, element, position):
        """在链表的任意位置添加元素"""
        if position > self._size or position < 0:
            raise IndexErrorOfStructure("Add failed! LinkedList index out of range")

        i = 0
        previous = self.dummy_head
        while i < position:
            previous = previous.next_node
            i += 1
        new = LinkedList.Node(element)
        new.next_node = previous.next_node
        previous.next_node = new
        self._size += 1

    def add_first(self, element):
        """在链表的开头添加元素"""
        self.add(element, 0)

    def add_last(self, element):
        """在链表的末尾添加元素"""
        self.add(element, self._size)

    def get(self, position):
        """获得链表任意位置的元素"""
        if position > self._size or position < 0:
            raise IndexErrorOfStructure("Get failed! LinkedList index out of range")
        i = 0
        current = self.dummy_head.next_node
        while i < position:
            current = current.next_node
            i += 1
        return current.data

    def get_first(self):
        return self.get(0)

    def get_last(self):
        return self.get(self._size - 1)

    def set(self, element, position):
        if position > self._size or position < 0:
            raise IndexErrorOfStructure("Set failed! LinkedList index out of range")
        i = 0
        current = self.dummy_head.next_node
        while i < position:
            current = current.next_node
            i += 1
        current.data = element

    def contains(self, element):
        current = self.dummy_head.next_node
        while current is not None:
            if current.data == element:
                return True
            current = current.next_node
        return False

    def remove(self, position):
        if position > self._size or position < 0:
            raise IndexErrorOfStructure("Remove failed! LinkedList index out of range")
        previous = self.dummy_head
        i = 0
        while i < position:
            previous = previous.next_node
            i += 1
        del_node = previous.next_node
        previous.next_node = del_node.next_node
        del_node.next_node = None
        self._size -= 1
        return del_node.data

    def remove_first(self):
        return self.remove(0)

    def remove_last(self):
        return self.remove(self._size - 1)

    def remove_element(self, element):
        previous = self.dummy_head
        while previous.next_node is not None:
            if previous.next_node.data == element:
                break
            previous = previous.next_node
        if previous.next_node is not None:
            del_node = previous.next_node
            previous.next_node = del_node.next_node
            del_node.next_node = None
            self._size -= 1